package com.open.capacity.finance.task.gdszcz;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.open.capacity.finance.config.Globals;
import com.open.capacity.finance.entity.SpringScheduledCron;
import com.open.capacity.finance.service.SpringScheduledCronService;
import com.open.capacity.finance.task.ScheduledOfTask;
import com.open.capacity.finance.util.GDSZCZUtils;
import com.open.capacity.reptile.constant.GDSZCZConstant;
import com.open.capacity.reptile.dao.GdszczMaEleExpFuncDao;
import com.open.capacity.reptile.dto.gdszcz.request.CommonRequest;
import com.open.capacity.reptile.dto.gdszcz.response.CommonResponse;
import com.open.capacity.reptile.dto.gdszcz.response.base.MaEleExpfuncData;
import com.open.capacity.reptile.dto.gdszcz.response.pz.glvou.GlVouDetailData;
import com.open.capacity.reptile.entity.*;
import com.open.capacity.reptile.service.*;
import com.open.capacity.reptile.util.HttpUtils;
import com.open.capacity.user.model.SysCompany;
import com.open.capacity.user.service.SysConfigService;
import com.open.capacity.utils.DateUtil;
import com.open.capacity.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 基础数据同步
 */
@Component
@Slf4j
public class BaseDataTask implements ScheduledOfTask {

    @Autowired
    private TaskExecutor taskExecutor;


    @Autowired
    private GdszczMaEleExpFuncService maEleExpFuncService;

    @Autowired
    private GdszczMaEleExpecoService maEleExpecoService;

    @Autowired
    private GdszczMaEleAccoService maEleAccoService;

    @Autowired
    private GdszczMaEleProjectService maEleProjectService;

    @Autowired
    private GdszczMaEleCurrentService maEleCurrentService;

    @Autowired
    private GdszczMaEleDepproService maEleDepproService;

    @Autowired
    private SpringScheduledCronService cronService;

    @Autowired
    private SysConfigService configService;

    @Autowired
    private GDSZCZUtils gdszczUtils;

    Integer cronId = null;

    @Override
    public void setCronId(Integer cronId) {
        this.cronId = cronId;
    }

    @Override
    public void execute() {
        try {
            log.info("start excute BaseDataTask");

            String updateStartTime = "";
            SpringScheduledCron cron = cronService.findById(cronId);
            if (cron != null && cron.getLastExcuteTime() != null) {
                updateStartTime = DateUtil.format(cron.getLastExcuteTime());
            }

            //异步将离线文件写入数据库
            String finalUpdateStartTime = updateStartTime;
            CompletableFuture.runAsync(() -> {
                trigger(finalUpdateStartTime);
            }, taskExecutor);

        } catch (Throwable e) {
            log.error("execute process has error(Throwable) : ", e);
        }
    }

    @Override
    public void trigger(String startTime) {
        String updateStartTime = String.valueOf(DateUtil.parseDate(startTime).getTime() / 1000);
        // 记录开始时间
        long start = System.currentTimeMillis();
        Date now = new Date();
        int currentYear = DateUtil.getYear();

        int fiscalYear = Integer.parseInt(configService.findByKey("gdszcz_fiscalYear").getCnfValue());
        if (StringUtil.isNotEmpty(startTime)) {
            fiscalYear = DateUtil.getYear(DateUtil.parseDate(startTime.substring(0, 10)));
        }

        try {
            Header[] headers = gdszczUtils.packetHeaders();

            String agencyCodeStr = configService.findByKey("gdszcz_agencyCode").getCnfValue();
            String[] agencyCodeArray = agencyCodeStr.split(",");
            for (String agencyCode : agencyCodeArray) {
                Optional<SysCompany> first = Globals.companyList.stream().filter(company -> company.getAgencyCode().equals(agencyCode)).findFirst();
                int startYear = fiscalYear;
                while (startYear <= currentYear) {
                    if (startYear <= 2020) {//不同步2021年前的数据
                        startYear++;
                        continue;
                    }

                    //1. 单位核算经济分类
                    syncMaEleExpeco(agencyCode, startYear, updateStartTime, first, headers);

                    //2. 单位核算支出功能科目
                    syncMaEleExpfunc(agencyCode, startYear, updateStartTime, first, headers);

                    //3. 会计科目
                    syncMaEleAcco(agencyCode, startYear, updateStartTime, first, headers);


                    //4. 往来单位
                    syncMaEleCurrent(agencyCode, startYear, updateStartTime, first, headers);
                    //5. 项目
                    syncMaEleProject(agencyCode, startYear, updateStartTime, first, headers);
                    //6. 预算项目
                    syncMaEleDeppro(agencyCode, startYear, updateStartTime, first, headers);

                    startYear++;
                }
            }

            //更新缓存
            Map<String, Object> param = new HashMap<>();
            param.put("isLeaf", 1);
            Globals.expecoList = maEleExpecoService.findAll(param);
            Globals.kjkmList = maEleAccoService.findAll(param);

            //更新最后执行成功时间
            cronService.updateExcuteTime(cronId, now, 1, null, (System.currentTimeMillis() - start) / 60000);
        } catch (Exception e) {
            log.error(e.getMessage());
            //更新最后执行失败时间
            cronService.updateExcuteTime(cronId, now, 0, e.getMessage(), (System.currentTimeMillis() - start) / 60000);
        }
    }


    /**
     * ma_ele_expeco  单位核算经济分类
     */
    private void syncMaEleExpeco(String agencyCode, Integer fiscalYear, String updateStartTime, Optional<SysCompany> first, Header[] headers) throws IOException {
        CommonRequest request = gdszczUtils.packetRequest(agencyCode, fiscalYear, updateStartTime, "ma_ele_expeco");
        String responseMaEleExpeco = HttpUtils.requestForJson(MessageFormat.format(GDSZCZConstant.ma_ele_expeco_query_url, configService.findByKey("gdszcz_apiurl").getCnfValue()), JSONObject.toJSONString(request), headers);

        CommonResponse<List<GdszczMaEleExpeco>> responseMaEleExpecoData = JSONObject.parseObject(responseMaEleExpeco, new TypeReference<CommonResponse<List<GdszczMaEleExpeco>>>() {
        });
        log.info(String.format("ma_ele_expeco_query_url--请求:agencyCode:{},fiscalYear:{},updateStartTime:{};响应:resultCode：{},resultMessage:{},resultCount:{}"), request.getAgencyCode(), request.getFiscalYear(), request.getUpdateStartTime(), responseMaEleExpecoData.getResultCode(), responseMaEleExpecoData.getResultMessage(), responseMaEleExpecoData.getData().size());
        if (responseMaEleExpecoData.getResultCode().equals("000")) {
            for (GdszczMaEleExpeco s : responseMaEleExpecoData.getData()) {
                int existCount = maEleExpecoService.exists(s.getChrId());
                if (existCount == 0) {
                    if (first.isPresent()) {
                        s.setAgencyCode(first.get().getId());
                    }
                    maEleExpecoService.save(s);
                }
            }
        }
    }

    /**
     * ma_ele_expfunc  单位核算支出功能科目
     */
    private void syncMaEleExpfunc(String agencyCode, Integer fiscalYear, String updateStartTime, Optional<SysCompany> first, Header[] headers) throws IOException {
        CommonRequest  request = gdszczUtils.packetRequest(agencyCode, fiscalYear, updateStartTime, "ma_ele_expfunc");
        String responseMaEleExpfunc = HttpUtils.requestForJson(MessageFormat.format(GDSZCZConstant.ma_ele_expfunc_query_url, configService.findByKey("gdszcz_apiurl").getCnfValue()), JSONObject.toJSONString(request), headers);

        CommonResponse<List<GdszczMaEleExpFunc>> responseMaEleExpfuncData = JSONObject.parseObject(responseMaEleExpfunc, new TypeReference<CommonResponse<List<GdszczMaEleExpFunc>>>() {
        });
        log.info(String.format("ma_ele_expfunc_query_url--请求:agencyCode:{},fiscalYear:{},updateStartTime:{};响应:resultCode：{},resultMessage:{},resultCount:{}"), request.getAgencyCode(), request.getFiscalYear(), request.getUpdateStartTime(), responseMaEleExpfuncData.getResultCode(), responseMaEleExpfuncData.getResultMessage(), responseMaEleExpfuncData.getData().size());
        if (responseMaEleExpfuncData.getResultCode().equals("000")) {
            for (GdszczMaEleExpFunc s : responseMaEleExpfuncData.getData()) {
                if (s.getIsDeleted() == 1) { //忽略已经删除的数据
                    continue;
                }
                int existCount = maEleExpFuncService.exists(s.getChrId());
                if (existCount == 0) {
                    if (first.isPresent()) {
                        s.setAgencyCode(first.get().getId());
                    }
                    maEleExpFuncService.save(s);
                }
            }
        }
    }

    /**
     * ma_ele_acco  会计科目
     */
    private void syncMaEleAcco(String agencyCode, Integer fiscalYear, String updateStartTime, Optional<SysCompany> first, Header[] headers) throws IOException {
        CommonRequest  request = gdszczUtils.packetRequest(agencyCode, fiscalYear, updateStartTime, "ma_ele_acco");
        String responseMaEleExpfunc = HttpUtils.requestForJson(MessageFormat.format(GDSZCZConstant.ma_ele_acco_query_url, configService.findByKey("gdszcz_apiurl").getCnfValue()), JSONObject.toJSONString(request), headers);

        CommonResponse<List<GdszczMaEleAcco>> responseMaEleAccoData = JSONObject.parseObject(responseMaEleExpfunc, new TypeReference<CommonResponse<List<GdszczMaEleAcco>>>() {
        });
        log.info(String.format("ma_ele_acco_query_url--请求:agencyCode:{},fiscalYear:{},updateStartTime:{};响应:resultCode：{},resultMessage:{},resultCount:{}"), request.getAgencyCode(), request.getFiscalYear(), request.getUpdateStartTime(), responseMaEleAccoData.getResultCode(), responseMaEleAccoData.getResultMessage(), responseMaEleAccoData.getData().size());
        if (responseMaEleAccoData.getResultCode().equals("000")) {
            for (GdszczMaEleAcco s : responseMaEleAccoData.getData()) {
                if (s.getIsDeleted() == 1) { //忽略已经删除的数据
                    continue;
                }
                int existCount = maEleAccoService.exists(s.getChrId());
                if (existCount == 0) {
                    if (first.isPresent()) {
                        s.setAgencyCode(first.get().getId());
                    }
                    maEleAccoService.save(s);
                }
            }
        }
    }

    /**
     * ma_ele_current  往来单位
     */
    private void syncMaEleCurrent(String agencyCode, Integer fiscalYear, String updateStartTime, Optional<SysCompany> first, Header[] headers) throws IOException {
        CommonRequest  request = gdszczUtils.packetRequest(agencyCode, fiscalYear, updateStartTime, "ma_ele_current");
        String responseMaEleExpfunc = HttpUtils.requestForJson(MessageFormat.format(GDSZCZConstant.ma_ele_current_query_url, configService.findByKey("gdszcz_apiurl").getCnfValue()), JSONObject.toJSONString(request), headers);

        CommonResponse<List<GdszczMaEleCurrent>> responseMaEleCurrentData = JSONObject.parseObject(responseMaEleExpfunc, new TypeReference<CommonResponse<List<GdszczMaEleCurrent>>>() {
        });
        log.info(String.format("ma_ele_current_query_url--请求:agencyCode:{},fiscalYear:{},updateStartTime:{};响应:resultCode：{},resultMessage:{},resultCount:{}"), request.getAgencyCode(), request.getFiscalYear(), request.getUpdateStartTime(), responseMaEleCurrentData.getResultCode(), responseMaEleCurrentData.getResultMessage(), responseMaEleCurrentData.getData().size());
        if (responseMaEleCurrentData.getResultCode().equals("000")) {
            for (GdszczMaEleCurrent s : responseMaEleCurrentData.getData()) {
                if (s.getIsDeleted() == 1) { //忽略已经删除的数据
                    continue;
                }
                int existCount = maEleCurrentService.exists(s.getChrId());
                if (existCount == 0) {
                    if (first.isPresent()) {
                        s.setAgencyCode(first.get().getId());
                    }
                    maEleCurrentService.save(s);
                }
            }
        }
    }

    /**
     * ma_ele_project  项目
     */
    private void syncMaEleProject(String agencyCode, Integer fiscalYear, String updateStartTime, Optional<SysCompany> first, Header[] headers) throws IOException {
        CommonRequest  request = gdszczUtils.packetRequest(agencyCode, fiscalYear, updateStartTime, "ma_ele_project");
        String responseMaEleExpfunc = HttpUtils.requestForJson(MessageFormat.format(GDSZCZConstant.ma_ele_project_query_url, configService.findByKey("gdszcz_apiurl").getCnfValue()), JSONObject.toJSONString(request), headers);

        CommonResponse<List<GdszczMaEleProject>> responseMaEleProjectData = JSONObject.parseObject(responseMaEleExpfunc, new TypeReference<CommonResponse<List<GdszczMaEleProject>>>() {
        });
        log.info(String.format("ma_ele_project_query_url--请求:agencyCode:{},fiscalYear:{},updateStartTime:{};响应:resultCode：{},resultMessage:{},resultCount:{}"), request.getAgencyCode(), request.getFiscalYear(), request.getUpdateStartTime(), responseMaEleProjectData.getResultCode(), responseMaEleProjectData.getResultMessage(), responseMaEleProjectData.getData().size());
        if (responseMaEleProjectData.getResultCode().equals("000")) {
            for (GdszczMaEleProject s : responseMaEleProjectData.getData()) {
                if (s.getIsDeleted() == 1) { //忽略已经删除的数据
                    continue;
                }
                int existCount = maEleProjectService.exists(s.getChrId());
                if (existCount == 0) {
                    if (first.isPresent()) {
                        s.setAgencyCode(first.get().getId());
                    }
                    maEleProjectService.save(s);
                }
            }
        }
    }

    /**
     * ma_ele_deppro  预算项目
     */
    private void syncMaEleDeppro(String agencyCode, Integer fiscalYear, String updateStartTime, Optional<SysCompany> first, Header[] headers) throws IOException {
        CommonRequest  request = gdszczUtils.packetRequest(agencyCode, fiscalYear, updateStartTime, "ma_ele_deppro");
        String responseMaEleExpfunc = HttpUtils.requestForJson(MessageFormat.format(GDSZCZConstant.ma_ele_deppro_query_url, configService.findByKey("gdszcz_apiurl").getCnfValue()), JSONObject.toJSONString(request), headers);

        CommonResponse<List<GdszczMaEleDeppro>> responseMaEleDepproData = JSONObject.parseObject(responseMaEleExpfunc, new TypeReference<CommonResponse<List<GdszczMaEleDeppro>>>() {
        });
        log.info(String.format("ma_ele_project_query_url--请求:agencyCode:{},fiscalYear:{},updateStartTime:{};响应:resultCode：{},resultMessage:{},resultCount:{}"), request.getAgencyCode(), request.getFiscalYear(), request.getUpdateStartTime(), responseMaEleDepproData.getResultCode(), responseMaEleDepproData.getResultMessage(), responseMaEleDepproData.getData().size());
        if (responseMaEleDepproData.getResultCode().equals("000")) {
            for (GdszczMaEleDeppro s : responseMaEleDepproData.getData()) {
                if (s.getIsDeleted() == 1) { //忽略已经删除的数据
                    continue;
                }
                int existCount = maEleDepproService.exists(s.getChrId());
                if (existCount == 0) {
                    if (first.isPresent()) {
                        s.setAgencyCode(first.get().getId());
                    }
                    maEleDepproService.save(s);
                }
            }
        }
    }

}

